package com.tianyi.role;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.tianyi.dao.entity.menu.Menu;
import com.tianyi.dao.entity.role.Role;
import com.tianyi.dao.entity.roleMenuRecord.RoleMenuRecord;
import com.tianyi.lib.model.WebResult;
import com.tianyi.lib.req.RoleReq;
import com.tianyi.menu.MenuService;
import com.tianyi.vo.PullDownVO;
import com.tianyi.vo.menu.MenuRoleVO;
import com.tianyi.vo.role.RoleDetailVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * role service
 *
 * @author cuixuhui
 * @date 2020/06/24
 */
@Service
public class RoleService {

    private static final Logger logger = LoggerFactory.getLogger(RoleService.class);

    @Autowired
    private RoleBaseService roleBaseService;
    @Autowired
    private MenuService menuService;

    public WebResult<String> preCheck(RoleReq req){

        if (StringUtils.isBlank(req.getRoleName())){
            return WebResult.error("角色名称不能为空");
        }
        if (StringUtils.isBlank(req.getRoleCode())){
            return WebResult.error("权限code不能为空");
        }
        if (Objects.isNull(req.getRoleLevel())){
            return WebResult.error("权限等级不能为空");
        }

        List<Role> roles = roleBaseService.queryExistRoleByReq(req);
        if (CollectionUtils.isNotEmpty(roles)){
            //List<Role> roleList = roles.stream().filter(ret -> !Objects.equals(ret.getId(), req.getId())).collect(Collectors.toList());
            //if (CollectionUtils.isNotEmpty(roleList)){
                return WebResult.error("权限已存在="+ JSON.toJSONString(roles));
            //}
        }

        //List<Long> menuIds = req.getMenuIds();
        //if (CollectionUtils.isEmpty(menuIds)){
        //    return WebResult.error("菜单id为空");
        //}
        //List<Menu> menus = menuService.queryMenusByIds(menuIds);
        //List<Long> existMenuIds = ListUtils.emptyIfNull(menus).stream().map(Menu::getId).collect(Collectors.toList());
        //List<Long> notExistMenuIds = menuIds.stream().filter(ret -> !existMenuIds.contains(ret)).collect(Collectors.toList());
        //if (CollectionUtils.isNotEmpty(notExistMenuIds)){
        //    return WebResult.error("菜单id= "+notExistMenuIds+" 不存在");
        //}
        return WebResult.ok("success");
    }

    private Role gentRoleByReq(RoleReq req){

        return gentRole(new Role(), req);
    }

    private Role gentRole(Role role, RoleReq req){
        if (Objects.isNull(role) || Objects.isNull(req)){
            return null;
        }
        if (Objects.isNull(req.getId())){
            role.setGmtCreate(new Date());
        }
        role.setGmtModified(new Date());
        role.setRoleName(req.getRoleName());
        role.setRoleCode(req.getRoleCode());
        role.setRoleLevel(req.getRoleLevel());
        return role;
    }

    private List<RoleMenuRecord> gentRoleMenuRecord(Long parentId, List<Long> menuIds){
        if (Objects.isNull(parentId) || CollectionUtils.isEmpty(menuIds)){
            return null;
        }
        List<RoleMenuRecord> roleMenuRecords = menuIds.stream().map(ret -> {
            RoleMenuRecord roleMenuRecord = new RoleMenuRecord();
            roleMenuRecord.setRoleId(parentId);
            roleMenuRecord.setMenuId(ret);
            return roleMenuRecord;
        }).collect(Collectors.toList());
        return roleMenuRecords;
    }

    public WebResult<String> addRoleRecord(RoleReq req) {

        WebResult<String> preCheck = preCheck(req);
        if (!preCheck.isSuccess()){
            return preCheck;
        }

        Role role = gentRoleByReq(req);
        roleBaseService.insertRole(role);
        roleBaseService.deleteRoleMenusByRoleId(req.getId());

        List<RoleMenuRecord> roleMenuRecords = gentRoleMenuRecord(role.getId(), req.getMenuIds());
        roleBaseService.batchInsertRoleMenus(roleMenuRecords);
        return WebResult.ok("success");
    }


    public WebResult<String> updateRole(RoleReq req) {

        Long roleId = req.getId();
        if (Objects.isNull(roleId)) {
            return WebResult.error("id 不能为空");
        }
        //WebResult<String> preCheck = preCheck(req);
        //if (!preCheck.isSuccess()){
        //    return preCheck;
        //}

        Role role = this.queryRoleByRoleId(roleId);
        if (Objects.isNull(role)) {
            return WebResult.error("record not exist");
        }
        role = gentRole(role, req);
        roleBaseService.updateRole(role);

        roleBaseService.deleteRoleMenusByRoleId(roleId);

        List<RoleMenuRecord> roleMenuRecords = gentRoleMenuRecord(role.getId(), req.getMenuIds());
        roleBaseService.batchInsertRoleMenus(roleMenuRecords);

        return WebResult.ok("success");
    }

    public WebResult<String> updateRoleNew(RoleReq req) {

        Long roleId = req.getId();
        if (Objects.isNull(roleId)) {
            return WebResult.error("id 不能为空");
        }
        Role role = this.queryRoleByRoleId(roleId);
        role = gentRole(role, req);
        roleBaseService.updateRole(role);
        roleBaseService.deleteRoleMenusByRoleId(roleId);
        List<RoleMenuRecord> roleMenuRecordsList = new ArrayList<>();
        for(Long menuId : req.getMenuIds()){
            RoleMenuRecord roleMenuRecordTemp = new RoleMenuRecord();
            roleMenuRecordTemp.setRoleId(req.getId());
            roleMenuRecordTemp.setMenuId(menuId);
            roleMenuRecordsList.add(roleMenuRecordTemp);
        }
        roleBaseService.insertRoleMenus(roleMenuRecordsList);

        return WebResult.ok("success");
    }

    public WebResult<String> deleteRoleById(RoleReq req) {
        Long roleId = req.getId();
        if (Objects.isNull(roleId)) {
            return WebResult.error("id 不能为空");
        }
        Role role = this.queryRoleByRoleId(roleId);
        if (Objects.isNull(role)) {
            return WebResult.error("record not exist");
        }

        roleBaseService.deleteRoleMenusByRoleId(roleId);

        return WebResult.ok("success");
    }

    public WebResult<List<PullDownVO>> getRolePullDown() {

        List<Role> roles = roleBaseService.queryAllRolePullDown();
        List<PullDownVO> vos = ListUtils.emptyIfNull(roles).stream().map(ret -> {
            PullDownVO vo = new PullDownVO();
            vo.setLabel(ret.getRoleName());
            vo.setValue(ret.getId());
            return vo;
        }).collect(Collectors.toList());

        return WebResult.ok(vos);
    }

    public WebResult<PageInfo<RoleMenuIds> > queryRolePage(RoleReq req) {

        PageInfo<RoleMenuIds> rolePageInfo = roleBaseService.queryRolePage(req);

        return WebResult.ok(rolePageInfo);
    }

    public WebResult<RoleDetailVO> getRoleDetail(RoleReq req) {

        Long roleId = req.getId();
        if (Objects.isNull(roleId)){
            return WebResult.error("roleId is null");
        }
        Role role = this.queryRoleByRoleId(roleId);
        if (Objects.isNull(role)) {
            return WebResult.error("record not exist");
        }

        RoleDetailVO vo = new RoleDetailVO();
        BeanUtils.copyProperties(role, vo);

        List<RoleMenuRecord> roleMenuRecords = roleBaseService.queryRoleMenusByRoleId(roleId);
        List<Long> menuIds = roleMenuRecords.stream().map(RoleMenuRecord::getMenuId).distinct().collect(Collectors.toList());
        List<Menu> menus = menuService.queryMenusByIds(menuIds);

        List<PullDownVO> pullDownVOS = ListUtils.emptyIfNull(menus).stream().map(ret -> {
            PullDownVO pullDownVO = new PullDownVO();
            pullDownVO.setValue(ret.getId());
            pullDownVO.setLabel(ret.getTitle());
            return pullDownVO;
        }).collect(Collectors.toList());
        vo.setMenuRolePullDownVO(pullDownVOS);
        return WebResult.ok(vo);
    }

    /**
     *
     * @param roleId
     * @return
     */
    public List<Long> getMenuIdsByRoleId(Long roleId) {

        List<RoleMenuRecord> roleMenuRecords = roleBaseService.queryRoleMenusByRoleId(roleId);
        List<Long> menuIds = ListUtils.emptyIfNull(roleMenuRecords).stream().map(RoleMenuRecord::getMenuId).collect(Collectors.toList());
        return menuIds;
    }

    public Role queryRoleByRoleId(Long roleId) {

        return roleBaseService.queryRoleByRoleId(roleId);
    }
}
